package com.nextwist.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.map.HashedMap;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;

import com.nexttwist.common.BaseException;
import com.nexttwist.common.Constants;
import com.nexttwist.common.DBContants;
import com.nexttwist.common.Type;
import com.nexttwist.pojo.EntryLine;
import com.nexttwist.pojo.Flag;
import com.nexttwist.pojo.Line;
import com.nexttwist.pojo.Story;
import com.nexttwist.pojo.Vote;

/**
 * This Class is used to get the data from the DB
 * 
 * @author Mintu
 * 
 */
public class StoryDAO extends BaseDAO {
	
	CommonDAO commonDAO = new CommonDAO();
	
	/**
	 * This method is used to delete a story, Its a soft delete and it ll delete all the related things
	 * @param storyId
	 * @return
	 */
	public boolean deleteStory(int storyId) throws BaseException{
		try{
			PreparedStatement getVoteUpPrepare = conn.prepareStatement(DBContants.GET_STORYLINE_BY_STORYID);
			getVoteUpPrepare.setInt(1, storyId);
			ResultSet rs = getVoteUpPrepare.executeQuery();
			rs.last();
			int count = rs.getRow();
			if(count == 1) {
				PreparedStatement deleteStoryPrepare = conn.prepareStatement(DBContants.DELETE_STORY);
				deleteStoryPrepare.setInt(1, storyId);
				int deleteStoryCheck = deleteStoryPrepare.executeUpdate();
				
				PreparedStatement deleteStoryLinePrepare = conn.prepareStatement(DBContants.DELETE_STORYLINE);
				deleteStoryLinePrepare.setInt(1, storyId);
				int deleteStoryLineCheck = deleteStoryLinePrepare.executeUpdate();
				
				PreparedStatement deleteEntryLinePrepare = conn.prepareStatement(DBContants.DELETE_ENTRYLINE);
				deleteEntryLinePrepare.setInt(1, storyId);
				int deleteEntryLineCheck = deleteEntryLinePrepare.executeUpdate();
				
				PreparedStatement deleteEntryLineVotePrepare = conn.prepareStatement(DBContants.DELETE_VOTE);
				deleteEntryLineVotePrepare.setInt(1, storyId);
				deleteEntryLineVotePrepare.executeUpdate();
				
				PreparedStatement deleteNotificationPrepare = conn.prepareStatement(DBContants.DELETE_NOTIFICATION_BYSTORYID);
				deleteNotificationPrepare.setInt(1, storyId);
				deleteNotificationPrepare.executeUpdate();
				
				
				if(deleteStoryCheck > 0 && deleteStoryLineCheck > 0 && deleteEntryLineCheck > 0){ 
					return true; 
				} else {
					return false;
				}
			} else {
				throw new Exception("Story has more than one line.");
			}
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to create new story
	 * @param storyObject
	 * @return storyId
	 */
	public int createStory(Story storyObject) throws BaseException{
		try{
			 String storyTitle = storyObject.getStoryTitle();
			 String storyLine = storyObject.getStoryLine();
			 int userId = storyObject.getUserId();
			 long time = Math.round(System.currentTimeMillis()/1000);
			 int storyId = commonDAO.getNewStoryId();
			 
			 PreparedStatement insertStoryPrepare = conn.prepareStatement(DBContants.ADD_STORY);
			 insertStoryPrepare.setInt(1, storyId);
			 insertStoryPrepare.setString(2, storyTitle);
			 insertStoryPrepare.setInt(3, userId);
			 insertStoryPrepare.setLong(4, time);
			 insertStoryPrepare.setString(5, storyObject.getType().toString());
			 int insertCheck = insertStoryPrepare.executeUpdate();
		 
			 PreparedStatement insertStoryLinePrepare = conn.prepareStatement(DBContants.ADD_STORY_LINE);
			 insertStoryLinePrepare.setInt(1, storyId);
			 insertStoryLinePrepare.setInt(2, 1);
			 insertStoryLinePrepare.setString(3, storyLine);
			 insertStoryLinePrepare.setInt(4, 0);
			 insertStoryLinePrepare.setInt(5, userId);
			 insertStoryLinePrepare.setLong(6, time);
			 insertStoryLinePrepare.setString(7, storyObject.getType().toString());
			
			 int insertStoryLineCheck = insertStoryLinePrepare.executeUpdate();
			 
			 
			 PreparedStatement insertEntryLinePrepare = conn.prepareStatement(DBContants.ADD_ENTRY_LINE);
			 insertEntryLinePrepare.setInt(1, storyId);
			 insertEntryLinePrepare.setInt(2, 1);
			 insertEntryLinePrepare.setInt(3, 1);
			 insertEntryLinePrepare.setString(4, storyLine);
			 insertEntryLinePrepare.setInt(5, userId);
			 insertEntryLinePrepare.setLong(6, time);
			 insertEntryLinePrepare.setString(7, storyObject.getType().toString());
			 int insertEntryLineCheck = insertEntryLinePrepare.executeUpdate(); 
			 
			 commonDAO.addtonotification(userId, storyId, 1, 0, 2, storyObject.getType());
			 if(insertStoryLineCheck > 0 && insertEntryLineCheck > 0 && insertCheck > 0){
				 return storyId;
			 } else {
				 return 0;
			 }
		 
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to update the story line and the title
	 * 
	 * We need to check the logic of this method need to confirm
	 * 
	 * @param storyObject
	 * @return storyId
	 */
	public int editStory(Story storyObject) throws BaseException{
		try{
			String storyTitle = storyObject.getStoryTitle();
			 String storyLine = storyObject.getStoryLine();
			 int storyId = storyObject.getStoryId();
			 PreparedStatement getVoteUpPrepare = conn.prepareStatement(DBContants.GET_STORYLINE_BY_STORYID);
				getVoteUpPrepare.setInt(1, storyId);
				ResultSet rs = getVoteUpPrepare.executeQuery();
				rs.last();
				int count = rs.getRow();
				if(count == 1) {
					 PreparedStatement updateStoryPrepare = conn.prepareStatement(DBContants.UPDATE_STORY);
					 updateStoryPrepare.setString(1, storyTitle);
					 updateStoryPrepare.setInt(2, storyId);
					 int checkUpdate = updateStoryPrepare.executeUpdate();
					if(checkUpdate > 0){
						PreparedStatement updateStoryLinePrepare = conn.prepareStatement(DBContants.UPDATE_STORYLINE);
						updateStoryLinePrepare.setString(1, storyLine);
						updateStoryLinePrepare.setInt(2, storyId);
						int checkLineUpdate = updateStoryLinePrepare.executeUpdate();
						if(checkLineUpdate > 0){
							//TODO: throw exception
							System.out.println("update successful");
						} else {
							//TODO: throw exception
							System.out.println("story table updated update successful");
						}
					} else {
						throw new BaseException(new Exception(), "500", "update fail");
					}
					return storyId;
				} else {
					throw new Exception("Story has more than one line.");
				}
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
    }
	
	/**
	 * This method is used to get the Entry lines
	 * @param storyId
	 * @param storyLineId
	 * @param userId
	 * @return List of entry lines
	 */
	public List<EntryLine> getEntryLine(int storyId, int storyLineId, int userId) throws BaseException{
		try{
			PreparedStatement getStoryLinePrepare = conn.prepareStatement(DBContants.GET_ENTRYLINE);
			getStoryLinePrepare.setInt(1, storyId);
			getStoryLinePrepare.setInt(2, storyLineId);
			ResultSet rs = getStoryLinePrepare.executeQuery();
			List<EntryLine> entryLines = new ArrayList<EntryLine>();
			EntryLine entryLineObj = new EntryLine();
			while(rs.next()){
				PreparedStatement getVoteUpPrepare = conn.prepareStatement(DBContants.GET_VOTES);
				getVoteUpPrepare.setInt(1, storyId);
				getVoteUpPrepare.setInt(2, rs.getInt("displayseq"));
				getVoteUpPrepare.setInt(3, 1);
				ResultSet voteResult = getVoteUpPrepare.executeQuery();
				voteResult.last();
				int voteUpCount = voteResult.getRow();
				
				PreparedStatement getVoteDownPrepare = conn.prepareStatement(DBContants.GET_VOTES);
				getVoteDownPrepare.setInt(1, storyId);
				getVoteDownPrepare.setInt(2, rs.getInt("displayseq"));
				getVoteUpPrepare.setInt(3, -1);
				ResultSet voteDownResult = getVoteDownPrepare.executeQuery();
				voteDownResult.last();
				int voteDownCount = voteDownResult.getRow();
				
				PreparedStatement getVote = conn.prepareStatement(DBContants.GET_VOTE_BY_USERID);
				getVote.setInt(1, storyId);
				getVote.setInt(2, rs.getInt("displayseq"));
				getVote.setInt(3, userId);
				ResultSet userVote = getVote.executeQuery();
				int usersVote = 0;
				while(userVote.next()){
					usersVote = userVote.getInt("vote");
				}
				
				int createdUserId = rs.getInt("crtdbyid");
				String credits = commonDAO.userLabel(createdUserId);
				int uniqueEntrylineId = rs.getInt("displayseq");
				String showTime = commonDAO.timeAgo(commonDAO.getEntryLineTime(uniqueEntrylineId));
				String avatarPath = commonDAO.userImage(createdUserId,"small");
				JSONObject usersObj = commonDAO.getUserDetails(createdUserId);
				String userName = usersObj.getString("userName");
				
				entryLineObj.setEntryLineId(rs.getInt("entrylineid"));
				entryLineObj.setEntryLine(rs.getString("entryline"));
				entryLineObj.setVoteUp(voteUpCount);
				entryLineObj.setVoteDown(voteDownCount);
				entryLineObj.setUserId(rs.getInt("crtdbyid"));
				entryLineObj.setUserName(userName);
				entryLineObj.setUserImagePath(avatarPath);
				entryLineObj.setUserLevel(credits);
				entryLineObj.setTimeAgo(showTime);
				entryLineObj.setUniqueId( rs.getInt("displayseq"));
				entryLineObj.setCurrentUserVote( usersVote);
				entryLineObj.setFlagCount( getFlagCount(rs.getInt("displayseq")));
				entryLines.add(entryLineObj);
			}
			return entryLines;
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to get the Story lines
	 * @param storyId
	 * @return List of story lines
	 */
	public String getStoryLine(int storyId) throws BaseException{
		try{
			PreparedStatement getStoryLinePrepare = conn.prepareStatement(DBContants.GET_STORYLINE_BY_STORYID);
			getStoryLinePrepare.setInt(1, storyId);
			ResultSet rs = getStoryLinePrepare.executeQuery();
			List<JSONObject> jsonList = new ArrayList<JSONObject>();
			while(rs.next()){
				int createdUserId = rs.getInt("crtdbyid");
				String credits = commonDAO.userLabel(createdUserId);
				String showTime = commonDAO.timeAgo(rs.getString("crtdtime"));
				String avatarPath = commonDAO.userImage(createdUserId,"small");
				JSONObject usersObj = commonDAO.getUserDetails(createdUserId);
				String userName = usersObj.getString("userName");
				
				JSONObject storyLineObj = new JSONObject();
				storyLineObj.put("storyLineId", rs.getInt("storylineid"));
				storyLineObj.put("storyLine", rs.getString("storyline"));
				storyLineObj.put("userId", createdUserId);
				storyLineObj.put("userName", userName);
				storyLineObj.put("userImagePath", avatarPath);
				storyLineObj.put("userLevel", credits);
				storyLineObj.put("timeAgo", showTime);
				
				jsonList.add(storyLineObj);							
			}
			return jsonList.toString();
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to insert a new line
	 * @param newlineObj
	 * @return boolean
	 */
	//TODO: add notifications
	public boolean insertLine(Line newlineObj) throws BaseException{
		try{
			int storyId = newlineObj.getStoryId();
			int entryLineId = commonDAO.getNewEntryid(storyId);
			int storyLineId = commonDAO.getNewStoryLineid(storyId);
			int userId = newlineObj.getUserId();
			String line = newlineObj.getNewline();
			
			long time = Math.round(System.currentTimeMillis() / 1000);
			 
			PreparedStatement insertLinePrepare = conn.prepareStatement(DBContants.ADD_ENTRY_LINE);
			insertLinePrepare.setInt(1, storyId);
			insertLinePrepare.setInt(2, storyLineId);
			insertLinePrepare.setInt(3, entryLineId);
			insertLinePrepare.setString(4, line);
			insertLinePrepare.setInt(5, userId);
			insertLinePrepare.setLong(6, time);
			insertLinePrepare.setString(7, newlineObj.getType().toString());
			int insertCheck = insertLinePrepare.executeUpdate();
			 commonDAO.addtonotification(userId, storyId, storyLineId, entryLineId, 3, newlineObj.getType());
			if(insertCheck > 0){
				return true;
			} else{
				return false;
			}
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to delete Entry line 
	 * @param storyId
	 * @param uniqueId
	 * @return boolean
	 */
	public boolean deleteLine(int storyId, int uniqueId) throws BaseException{
		try{
			 PreparedStatement updateLinePrepare = conn.prepareStatement(DBContants.DELETE_ENTRYLINE_BYID);
			 updateLinePrepare.setInt(1, storyId);
			 updateLinePrepare.setInt(2, uniqueId);
			 int checkUpdate = updateLinePrepare.executeUpdate();
			 if(checkUpdate > 0 ){
				 PreparedStatement updateNotificationPrepare = conn.prepareStatement(DBContants.DELETE_NOTIFICATION_BYENTRYLINEID);
				 updateNotificationPrepare.setInt(1, storyId);
				 updateNotificationPrepare.setInt(2, uniqueId);
				 int checkNotiUpdate = updateNotificationPrepare.executeUpdate();
				 if(checkNotiUpdate > 0){
					 return true;
				 } else {
					 return false;
				 }
			 } else {
				 return false;
			 }
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}

	/**
	 * This method is used to add Flag in a entry line
	 * @param flagObject
	 * @return boolean
	 */
	public boolean reportFlag(Flag flagObject) throws BaseException{
		try{
			int uniqueId = flagObject.getUniqueId();
			int storyId = flagObject.getStoryId();
			int userId = flagObject.getUserId();
			int createdBy = flagObject.getCrtdbyid();
			long time = Math.round(System.currentTimeMillis() / 1000);
			PreparedStatement insertFlagPrepare = conn.prepareStatement(DBContants.ADD_REPORT_FLAG);
			insertFlagPrepare.setInt(1, uniqueId);
			insertFlagPrepare.setInt(2, storyId);
			insertFlagPrepare.setInt(3, createdBy);
			insertFlagPrepare.setInt(4, userId);
			insertFlagPrepare.setString(5, String.valueOf(time));
			int checkInsert = insertFlagPrepare.executeUpdate();
			
			if(checkInsert > 0){
				PreparedStatement selectFlagPrepare = conn.prepareStatement(DBContants.GET_FLAG);
				selectFlagPrepare.setInt(1, uniqueId);
				ResultSet rs = selectFlagPrepare.executeQuery();
				rs.last();
				int count = rs.getRow();
				//TODO: need to move this number to property file
				if(count > 9){
					PreparedStatement updateEntryLinePrepare = conn.prepareStatement(DBContants.DELETE_ENTRYLINE_BYID);
					updateEntryLinePrepare.setInt(1, storyId);
					updateEntryLinePrepare.setInt(2, uniqueId);
					updateEntryLinePrepare.executeUpdate();
					PreparedStatement updateEntryLineVotePrepare = conn.prepareStatement(DBContants.GET_VOTE_BY_ENTRYLINEID);
					updateEntryLineVotePrepare.setInt(1, uniqueId);
					updateEntryLineVotePrepare.executeUpdate();
				}
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}	
		
		
	}
	
	/**
	 * This method is used to get the Flag count for a entryline
	 * @param uniqueId
	 * @return number of flag
	 */
	public int getFlagCount(int uniqueId) throws BaseException{
		try{
			PreparedStatement selectFlagPrepare = conn.prepareStatement(DBContants.GET_FLAG);
			selectFlagPrepare.setInt(1, uniqueId);
			ResultSet rs = selectFlagPrepare.executeQuery();
			rs.last();
			return rs.getRow();
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to give the vote in a line
	 * @param voteObj
	 * @return boolean
	 */
	public boolean giveVote(Vote voteObj) throws BaseException{
		try{
			int uniqueId = voteObj.getUniqueId();
			int storyId = voteObj.getStoryId();
			int vote = voteObj.getVote();
			int userId = voteObj.getUserId();
			
			PreparedStatement getPrepare = conn.prepareStatement(DBContants.GET_VOTE_BY_USERID);
			getPrepare.setInt(1, storyId);
			getPrepare.setInt(2, uniqueId);
			getPrepare.setInt(3, userId);
			ResultSet rs = getPrepare.executeQuery();
			while(rs.next()){
				int oldVote = rs.getInt("vote");
				if((oldVote == -1 && vote == 1) || (oldVote == 1 && vote == -1)) {
					PreparedStatement updatePrepare = conn.prepareStatement(DBContants.DELETE_VOTE_BYUSERID);
					updatePrepare.setInt(1, uniqueId);
					updatePrepare.setInt(2, userId);
					updatePrepare.executeUpdate();
				} else {
					return false;
				}
			}
			int createdById = 0;
			int storyLineId = 0;
			String storyLine = "";
			String type = Type.story.toString();
			PreparedStatement getUserPrepare = conn.prepareStatement(DBContants.GET_ENTRYLINE_BYID);
			getUserPrepare.setInt(1, uniqueId);
			ResultSet result = getUserPrepare.executeQuery();
			while(result.next()){
				createdById = result.getInt("crtdbyid");
				storyLineId = result.getInt("storylineid");
				storyLine = result.getString("entryline");
				type = result.getString("type");
				break;
			}
			result.last();
			int rowCount = result.getRow();
			long time = Math.round(System.currentTimeMillis() / 1000);
			PreparedStatement insertPrepare = conn.prepareStatement(DBContants.ADD_ENTRY_LINE_VOTE);
			insertPrepare.setInt(1, storyId);
			insertPrepare.setInt(2, uniqueId);
			insertPrepare.setInt(3, userId);
			insertPrepare.setInt(4, vote);
			insertPrepare.setInt(5, createdById);
			insertPrepare.setString(6, String.valueOf(time));
			insertPrepare.setString(7, type);
			insertPrepare.executeUpdate();
			
			commonDAO.addtonotification(userId, storyId, storyLineId, uniqueId, vote, Type.valueOf(type));
			
			int voteUpCount = commonDAO.getVoteUpCount(uniqueId);
			if(voteUpCount >= Constants.VOTE_COUNT){
				int newStoryLineId = commonDAO.getNewStoryLineid(storyId);
				PreparedStatement insertStoryLine = conn.prepareStatement(DBContants.ADD_STORY_LINE);
				insertStoryLine.setInt(1, storyId);
				insertStoryLine.setInt(2, newStoryLineId);
				insertStoryLine.setString(3, storyLine);
				insertStoryLine.setInt(4, rowCount);
				insertStoryLine.setInt(5, createdById);
				insertStoryLine.setString(6, String.valueOf(time));
				insertStoryLine.executeUpdate();
				commonDAO.addtonotification(userId, storyId, storyLineId, uniqueId, 5, Type.valueOf(type));
			}
			return true;
				
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	/**
	 * This method is used to search the stories by their story title
	 * @param searchLine
	 * @return List of story object
	 */
	public String searchStory(String searchLine)throws BaseException{
		try{
			searchLine.toUpperCase();
			JSONArray jsonArray = new JSONArray();
			PreparedStatement searchPrepare = conn.prepareStatement("SELECT * FROM story WHERE delflag = 'N' and UPPER(storyname) LIKE ?");
			searchPrepare.setString(1, "%"+searchLine+"%");
			ResultSet rs = searchPrepare.executeQuery();
			while(rs.next()){
				JSONObject obj = new JSONObject();
				int storyId = rs.getInt("storyid");
				PreparedStatement getCreatedBy = conn.prepareStatement("SELECT crtdbyid FROM story WHERE storyid = ?");
				getCreatedBy.setInt(1, storyId);
				ResultSet getCrtdBy = getCreatedBy.executeQuery();
				String userName = "";
				String imagePath = "";
				int userCrtd = 0;
				while(getCrtdBy.next()){
					userCrtd = getCrtdBy.getInt("crtdbyid");
					JSONObject userObj = commonDAO.getUserDetails(userCrtd);
					userName = userObj.getString("userName");
					imagePath = commonDAO.userImage(userCrtd, "small");
				}
				int lineCount = 0;
				String storyLine = "";
				PreparedStatement getStoryLine = conn.prepareStatement("select count(storyid) as cnt, storyline from storyline where storyid = ? GRoup BY storyid"); 
				getStoryLine.setInt(1, storyId);
				ResultSet getLineResult = getStoryLine.executeQuery();
				while(getLineResult.next()){
					lineCount = getLineResult.getInt("cnt");
					storyLine = getLineResult.getString("storyline");
				}
				obj.put("storyId", storyId);
				obj.put("storyName", rs.getString("storyname"));
				obj.put("storyLine", storyLine);
				obj.put("lineCount", lineCount);
				obj.put("userId", userCrtd);
				obj.put("userName", userName);
				obj.put("imagePath", imagePath);
				jsonArray.put(obj);
			}
			return jsonArray.toString();
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	
	public List<Story> findHotStories() throws Exception {
		try {
			PreparedStatement getAllStory = conn.prepareStatement(DBContants.GET_ALL_STORIES);
			ResultSet rs = getAllStory.executeQuery();
			Map<Integer, Integer> voteCounts = new HashMap<Integer, Integer>();
			Map<Integer, Story> allStory = new HashMap<Integer, Story>();
			while(rs.next()){
				
				int storyId = rs.getInt("storyid");
				Story storyObj = new Story();
				storyObj.setStoryId(storyId);
				storyObj.setStoryTitle(rs.getString("storyname"));
				storyObj.setType(Type.valueOf(rs.getString("type")));
				allStory.put(storyId, storyObj);
				
				PreparedStatement getCounts = conn.prepareStatement(DBContants.VOTE_COUNT_FOR_HOT_STORY);
				getCounts.setInt(1, storyId);
				ResultSet voteResultSet = getCounts.executeQuery();
				while(voteResultSet.next()){
					voteCounts.put(storyId, voteResultSet.getInt("votes")+voteResultSet.getInt("entryid"));
				}
				
				PreparedStatement getUserCount = conn.prepareStatement(DBContants.USER_COUNT_IN_STORY);
				getUserCount.setInt(1, storyId);
				ResultSet userCountResultSet = getUserCount.executeQuery();
				while(userCountResultSet.next()){
					voteCounts.put(storyId, Integer.valueOf(voteCounts.get(storyId).intValue() + userCountResultSet.getInt("uid")));
				}
			}
			Map<Integer, Integer> sortedStory = sortByValues(voteCounts);
			
			List<Story> stories = new ArrayList<Story>();
			
			Iterator iterator = sortedStory.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry mapEntry = (Map.Entry) iterator.next();
				stories.add(allStory.get(mapEntry.getKey()));
			}
			
			System.out.println(sortedStory.toString());
			return stories;
		} catch (Exception e) {
			throw new BaseException(e, "500", e.getMessage());
		}
	}
	
	public List<Story> getFreshStories() throws Exception {
		
		PreparedStatement getAllStory = conn.prepareStatement(DBContants.GET_FRESH_STORY);
		ResultSet rs = getAllStory.executeQuery();
		List<Story> freshStories = new ArrayList<Story>();
		while(rs.next()){
			int storyId = rs.getInt("sid");
			freshStories.add(getStoryById(storyId));
		}
		return freshStories;
	}
	
	public Story getStoryById(int storyId) throws SQLException {
		PreparedStatement getStory = conn.prepareStatement(DBContants.GET_STORY_BY_ID);
		getStory.setInt(1, storyId);
		ResultSet rs = getStory.executeQuery();
		Story storyObj = new Story();
		while(rs.next()){
			storyObj.setStoryId(rs.getInt("storyid"));
			storyObj.setStoryTitle(rs.getString("storyname"));
			storyObj.setType(Type.valueOf(rs.getString("type")));
			storyObj.setUserId(rs.getInt("crtdbyid"));
		}
		return storyObj;
	}
	
	/*
     * Java method to sort Map in Java by value e.g. HashMap or Hashtable
     * throw NullPointerException if Map contains null values
     * It also sort values even if they are duplicates
     */
    public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map){
        List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet());
      
        Collections.sort(entries, new Comparator<Map.Entry<K,V>>() {

            @Override
            public int compare(Entry<K, V> o1, Entry<K, V> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
      
        //LinkedHashMap will keep the keys in the order they are inserted
        //which is currently sorted on natural ordering
        Map<K,V> sortedMap = new LinkedHashMap<K,V>();
      
        for(Map.Entry<K,V> entry: entries){
            sortedMap.put(entry.getKey(), entry.getValue());
        }
      
        return sortedMap;
    }

	
}
